package com.isec.base.monit.web;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.LRUCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.common.DateUtil;
import com.common.FileUtil;
import com.core.extend.excel.ExcelUtils;
import com.core.security.page.AutoPage;
import com.core.security.page.JsonResult;
import com.core.security.page.PageSupport;
import com.core.tools.AppUserTool;
import com.core.tools.DBTool;
import com.core.tools.FinalVarStaticTool;
import com.core.tools.PropertiesTool;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.isec.base.monit.dto.DownPmDto;
import com.isec.base.monit.dto.DownSourceDto;
import com.isec.base.monit.dto.PmDto;
import com.isec.base.monit.dto.SourceDto;
import com.isec.base.monit.dto.UserDto;
import com.isec.base.monit.service.PmService;
import com.isec.base.monit.service.SourceService;
import com.isec.base.monit.service.UserService;
import com.isec.util.ExportExcelUtil;

import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

@Controller
@RequestMapping("/api")
public class ApiController {

	@Autowired
	UserService userService;

	//升级为节点用户页面
	@RequestMapping("/uptoGradePage")
	public ModelAndView uptoGradePage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("/module/base/list/upgrade");
		return model;
	}

	//权限控制页面
	@RequestMapping("/rbacPage")
	public ModelAndView rbacPage() {
		ModelAndView model = new ModelAndView();
		model.addObject("users", userService.loadAllUser());
		model.addObject("userfs", userService.loadAllFiles());
		model.setViewName("/module/base/list/rbacpage");
		return model;
	}


	@RequestMapping("/logout")
	@ResponseBody
	public JsonResult logout() {
		JsonResult j = new JsonResult();
		if(AppUserTool.isLogin(AppUserTool.getSessionId())) {
			AppUserTool.removeAppUser();
			j.setData(true);
		}else {
			j.setData(false);
		}
		return j;
	}

	@RequestMapping("/initNode")
	@ResponseBody
	public JsonResult initNode(HttpServletRequest request) {
		String u = request.getParameter("u");
		String p = request.getParameter("p");
		String ip = request.getParameter("ip");
		String port = request.getParameter("port");
		String db = request.getParameter("db");
		String url = "jdbc:mysql://"+ip+":"+port+"/"+db+"?useSSL=false&characterEncoding=utf-8&autoReconnect=true";
		JsonResult j = new JsonResult();
		j.setData(false);
		try {
			if(DBTool.isConnect(u, p, url)) {
				DBTool.runScript(u, p, url);
				userService.saveNode(db,u, p, url);
				userService.upgradeLevel();
				j.setData(true);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return j;
	}

	@RequestMapping("/user")
	@ResponseBody
	public JsonResult userInfo() {
		JsonResult j = new JsonResult();
		if(AppUserTool.isLogin(AppUserTool.getSessionId())) {
			j.setData(userService.loadUser());
		}else {
			j.setData(null);
		}
		return j;
	}

	@RequestMapping("/loaduser")
	@ResponseBody
	public JsonResult loadAllUser() {
		JsonResult j = new JsonResult();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("user", userService.loadUser());
		map.put("ufs", userService.loadUserFiles());
		j.setData(PageSupport.loadObjHtml("/module/base/list/users.htm", map));
		return j;
	}

	@Autowired
	org.springframework.core.env.Environment env;

	@Autowired
	PmService pmService;

	@Autowired
	SourceService sourceService;

	/**
	 * Upload界面
	 * 上传pM数据并解析
	 * @throws IOException
	 */
	@RequestMapping("/uploadpm")
	@ResponseBody
	public boolean uploadPm(@RequestParam("file") MultipartFile multipartFile) throws IOException {
		try {
			List<Map<Integer, Object>> dataList = ExcelUtils.readExcelWithFiexPos(multipartFile,0,0,-1);
			List<PmDto> pms = pmService.analyzePms(dataList);
			pmService.savePms(pms);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Upload界面
	 * 上传source数据并解析
	 * @throws IOException
	 */
	@RequestMapping("/uploadsource")
	@ResponseBody
	//@RequestParam("file") MultipartFile file
	public boolean uploadSource(@RequestParam("file") MultipartFile multipartFile) throws IOException {
		try {
			List<Map<Integer, Object>> dataList = ExcelUtils.readExcelWithFiexPos(multipartFile,0,0,-1);
			List<SourceDto> sources = sourceService.analyzeSources(dataList);
			sourceService.saveSources(sources);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 注册界面
	 * 用于用户附件上传
	 * 先上传附件，附件先存库，再提交用户信息保存
	 * @return Map{}
	 * @throws IOException
	 */
	@RequestMapping("/uploadfile")
	@ResponseBody
	public List<Map<String, String>> uploadFile(@RequestParam("file") MultipartFile[] files, HttpServletRequest request) throws IOException {
		String email = request.getParameter("email");
		if (files.length < 0 || StringUtils.isBlank(email)) {
			return new ArrayList<>();
		}
		//获取用户已上传的文件个数进行限制
		int userFiles = userService.loadUserFilesCount(email);
		if(userFiles >= 5) {
			return new ArrayList<>();
		}

		// 获取用户指定的文件夹，业务隔离
		String dir = PropertiesTool.getString("files.local.path");
		return userService.batchUpload(files, dir,email);
	}


	/**
	 * 用户基本信息界面
	 * 查询用户上传的所有文件材料
	 * @return  user_id
	 *			file_id	文件ID
	 *			file_realname 文件真实名称，上传时的用户文件名
	 *			file_fname	系统生成的唯一文件名
	 *			file_path
	 *			file_abspath
	 */
	@RequestMapping("/loadUserFiles")
	public List<Map<String, Object>> loadUserFiles() {
		return userService.loadUserFiles();
	}

	/**
	 * 用户基本信息界面
	 * 下载用户文件
	 */
	@RequestMapping("/downUserFiles/{fid}")
	public void downUserFiles(@PathVariable("fid") String fid,HttpServletResponse response) {
		Map<String, Object> file = userService.loadUserFile(fid);
		if (null != file) {
//			String dir = PropertiesTool.getString("files.local.path");
			FileUtil.downloadFile(response, file.get("file_abspath").toString() + file.get("file_fname").toString() , file.get("file_realname").toString());
		}
	}

	/**
	 * Upload界面
	 * 保存数据
	 * @param t PM/SOURCE
	 * @param datas
	 * @return
	 */
	@RequestMapping("/sd/{dt}")
	@ResponseBody
	public synchronized boolean saveData(@PathVariable("dt")String t,HttpServletRequest request) {
		FinalVarStaticTool.ISUPLOAD_DATA = true;//表示当前正在上传数据，避免数据校验出现异常
		String data = request.getParameter("data");
		boolean flag = false;
		try {
			data = URLDecoder.decode(data, "UTF-8");
			JSONArray arrs = JSONUtil.parseArray(data);
			if (StringUtils.equals(t, "PM")) {
				flag = pmService.saveData(arrs);
			}
			if (StringUtils.equals(t, "SOURCE")) {
				flag = sourceService.saveData(arrs);
			}
			UserDto user = userService.loadUser();
			userService.saveHy(PropertiesTool.getString("data.upload.agreement.content"),
					AppUserTool.getAppUser().getUserID(),
					DateUtil.dateFormat(new Date(),DateUtil.DATE_PATTERN), user.getUser_nameimg(), "1");
		} catch (Exception e) {
			e.printStackTrace();
		}
		FinalVarStaticTool.ISUPLOAD_DATA = false;//表示当前正在上传数据，可以进行数据校验
		return flag;
	}

	LRUCache<String, JSONArray> cache = CacheUtil.newLRUCache(50);

	/**
	 * Data界面
	 * 查询全球分布
	 * @param dt 数据类型/PM/SOURCE
	 * @param ct 元素类型/C/N/O [all或空  查询所有]
	 * @return Content,Longitude,Latitude
	 */
	@RequestMapping("/ld/{dt}/{ct}")
	@ResponseBody
	public JSONArray loadData(@PathVariable("dt") String dt,@PathVariable("ct") String ct) {
		if (StringUtils.equals(ct, "all") || StringUtils.isEmpty(ct)) {
			if (!cache.containsKey("ALL_" + dt)) {
				if (StringUtils.equals(dt, "PM")) {
					cache.put("ALL_" + dt, pmService.loadData(ct));
				}
				if (StringUtils.equals(dt, "SOURCE")) {
					cache.put("ALL_" + dt, sourceService.loadData(ct));
				}
			}
			return cache.get("ALL_"+dt);
		}else{
			if (!cache.containsKey(dt+"_"+ct)){
				if (StringUtils.equals(dt, "PM")) {
					cache.put(dt+"_"+ct, pmService.loadData(ct));
				}
				if (StringUtils.equals(dt, "SOURCE")) {
					cache.put(dt+"_"+ct, sourceService.loadData(ct));
				}
			}
			return  cache.get(dt+"_"+ct);
		}
	}


	//	@RequestMapping("/search/{dt}/{ct}")
	//	@ResponseBody
	//	public JSONArray searchData(@PathVariable("dt") String dt,@PathVariable("ct") String ct) {
	//		if (StringUtils.equals(dt, "PM")) {
	//			return pmService.searchData(ct);
	//		}
	//		if (StringUtils.equals(dt, "SOURCE")) {
	//			return sourceService.searchData(ct);
	//		}
	//		return new JSONArray();
	//	}


	/**
	 * PM/SOURCE界面 search
	 * 查询全球分布
	 * @param dt 数据类型/PM/SOURCE
	 * @param ct 元素类型/C/N/O [all或空  查询所有]
	 * @return Content,Longitude,Latitude
	 */
	@RequestMapping("/search/{dt}/{ct}")
	@ResponseBody
	public JsonResult searchData(@RequestParam String jsonpage,@PathVariable("dt") String dt,@PathVariable("ct") String ct) {
		if (StringUtils.equals(dt, "PM")) {
			AutoPage<DownPmDto> page = PageSupport.fromJsonAutoPage(jsonpage.toString());
			page = pmService.searchData(page,ct);
			PageSupport.loadGridHtml("/module/base/list/pmList", page);
			return new JsonResult(page);
		}
		if (StringUtils.equals(dt, "SOURCE")) {
			AutoPage<DownSourceDto> page = PageSupport.fromJsonAutoPage(jsonpage.toString());
			page = sourceService.searchData(page,ct);
			PageSupport.loadGridHtml("/module/base/list/sourceList", page);
			return new JsonResult(page);
		}
		return new JsonResult();
	}

	/**
	 * PM/SOURCE界面 元素周期表
	 * 查询全球分布
	 * @param dt 数据类型/PM/SOURCE
	 * @return List<SourceDto> -->SourceDto 仅返回Content 元素名
	 */
	@RequestMapping("/pte/{dt}")
	@ResponseBody
	public JsonResult loadPte(@PathVariable("dt") String dt) {
		if (StringUtils.equals(dt, "PM")) {
			return new JsonResult(pmService.loadPte());
		}
		if (StringUtils.equals(dt, "SOURCE")) {
			return new JsonResult(sourceService.loadPte());
		}
		return new JsonResult();
	}


	/**
	 * 数据下载界面，显示数据下载合约
	 * op:合约类型 download 下载数据合约  upload 上链合约
	 * @return
	 */
	@RequestMapping("/showhy/{op}")
	@ResponseBody
	public JSONObject showDownHy(@PathVariable("op")String op) {
		UserDto user = userService.loadUser();
		if (null == user) {
			return new JSONObject();
		}
		JSONObject hy = new JSONObject();
		hy.set("dataDownloadAgreementContent", PropertiesTool.getString("data."+op+".agreement.content")); //合约内容
		try {
			hy.set("dataDownloadAgreementDate", DateUtil.dateFormat(new Date(),DateUtil.DATE_PATTERN)); //日期
			hy.set("dataDownloadAgreementJob", user.getUser_interests()); //role
			hy.set("dataDownloadAgreementUimg", user.getUser_nameimg()); //签名 base64 images
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return hy;
	}

	/**
	 * PM/SOURCE界面 search href
	 * @param dt 数据类型/PM/SOURCE 
	 * @param w 查询条件 [{IsotopeType:"",No:"",Type:"",Content:""},{IsotopeType:"",No:"",Type:"",Content:""}]
	 * @return
	 */
	@RequestMapping(value = "/down/{dt}",produces="application/json;charset=UTF-8")
	public void downloadData(@PathVariable("dt") String dt , HttpServletRequest request, HttpServletResponse response) {
		UserDto user = userService.loadUser();
		if (null == user) {
			return;
		}
		String param = request.getParameter("w");//查询条件
		OutputStream outputStream = null;
		try {
			outputStream = response.getOutputStream();
			String fileName = URLEncoder.encode(dt + " DATA LIST", StandardCharsets.UTF_8.name());//文件名
			response.setContentType("application/octet-stream;charset=UTF-8");
			response.setCharacterEncoding("utf-8");
			response.addHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xls");
			response.addHeader("Set-Cookie", "fileDownload=true;path=/");
			if (StringUtils.equals(dt, "PM")) {
				List<String[]> datas = pmService.downData(param);
				String[] headers = new String[] {"No.","Isotope Type","PM Type","Content","Isotopic Composition (‰)","SD","n","Mass Concentration (%)","SD","Sampling Date","Year","Season","Sampling Site","Nation","Region","Latitude(S-,N+)","Longitude(W-,E+)","Laboratory","Reference"}; 
				ExportExcelUtil.exportExcel("PM",headers,datas,outputStream);
			}
			if (StringUtils.equals(dt, "SOURCE")) {
				List<String[]> datas = sourceService.downData(param);
				String[] headers = new String[] {"No.","Isotope Type","Source Type","Content","Isotopic Composition (‰)","SD","n","Sampling Date","Year","Season","Sampling Site","Nation","Region","Latitude(S-,N+)","Longitude(W-,E+)","Laboratory","Reference","Note"}; 
				ExportExcelUtil.exportExcel("SOURCE",headers,datas,outputStream);
			}
			userService.saveHy(PropertiesTool.getString("data.download.agreement.content"),
					user.getUser_id(),
					DateUtil.dateFormat(new Date(),DateUtil.DATE_PATTERN), user.getUser_nameimg(), "2");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (outputStream != null) {
				try {
					outputStream.flush();//刷新流：通道中数据全部输出
					outputStream.close();//关闭流
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}


	/**
	 * 查询用户基本信息
	 * myinfo界面
	 * @return
	 */
	@RequestMapping("/ui")
	@ResponseBody
	public String loadUserInfo() {
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("user", userService.loadUser());
		map.put("ufs", userService.loadUserFiles());
		return PageSupport.loadObjHtml("module/base/page/myinfo/myinfo", map);
	}

	/**
	 * 查询用户基本信息 用戶身份升級為節點用戶
	 * myinfo界面 
	 * @return
	 */
	@RequestMapping("/upgrade")
	@ResponseBody
	public boolean upgradeLevel() {
		userService.upgradeLevel();
		return true;
	}

	/**
	 * 登录  ： 0 暂未审核  1 正常登录 2 被锁定 3用户名或密码错误 4 验证码错误
	 * @return 0成功1验证码错误
	 */
	@RequestMapping("/login")
	@ResponseBody
	public int login(HttpServletRequest request) {
		String verificationCode = request.getParameter("v");
		String captcha = request.getSession().getAttribute("captcha").toString();
		if (StringUtils.isEmpty(verificationCode)||!captcha.equalsIgnoreCase(verificationCode)){
			return 4;//验证码错误
		}
		String userId = request.getParameter("u");
		String pwd = request.getParameter("p");
		return userService.checkLogin(userId, pwd, ServletUtil.getClientIP(request));
	}

	/**
	 * 注册
	 * @return 
	 * @return
	 */
	@RequestMapping("/regis")
	@ResponseBody
	public int regis(HttpServletRequest request) {
		String verificationCode = request.getParameter("v");
		String captcha = request.getSession().getAttribute("captcha").toString();
		if (StringUtils.isEmpty(verificationCode)||!captcha.equalsIgnoreCase(verificationCode)){
			return 1;//验证码错误
		}

		String userName = request.getParameter("u");
		String pwd = request.getParameter("p");
		String email = request.getParameter("email");
		String page = request.getParameter("page");
		String org = request.getParameter("org");
		String interests = request.getParameter("interests");
		String datapair = request.getParameter("datapair");
		UserDto user = new UserDto();
		user.setUser_email(email);
		user.setUser_name(userName);
		user.setUser_id(IdUtil.fastSimpleUUID());
		user.setUser_no(IdUtil.getSnowflakeNextIdStr());
		user.setUser_ip(ServletUtil.getClientIP(request));
		user.setUser_org(org);
		user.setUser_interests(interests);
		if (!StringUtils.startsWith(page, "http://") && !StringUtils.startsWith(page, "https://")) {
			page = "http://" + page;
		}
		user.setUser_page(page);
		user.setUser_pwd(pwd);
		user.setUser_nameimg(datapair);
		userService.register(user) ;
		return 0;//注册成功
	}
	
	/**
	 * 用户管理界面
	 * 用户状态激活
	 * @param request
	 * @return
	 */
	@RequestMapping("/active")
	@ResponseBody
	public boolean activeUser(HttpServletRequest request) {
		String userId = request.getParameter("u"); //用户ID
		String status = request.getParameter("s"); //是否激活 0锁定1激活
		return userService.activeUser(userId,status);
	}


	/**
	 * 用户密码修改界面
	 * 用户邮箱验证码发送
	 * @param request
	 * @return
	 */
	@RequestMapping("/send")
	@ResponseBody
	public boolean send(HttpServletRequest request) {
		String email = request.getParameter("email");
		return userService.sendEmail(email);
	}

	/**
	 * 检查用户邮箱是否已经存在
	 * @param request email
	 * @return false 不存在 true 已存在
	 */
	@RequestMapping("/emailIsExist")
	@ResponseBody
	public boolean emailIsExist(HttpServletRequest request) {
		String email = request.getParameter("email");
		return userService.emailIsExist(email);
	}

	/**
	 * 用户密码修改界面
	 * 用户邮箱验证码发送
	 * @param code 表示用户输入的验证码
	 * @return true验证码正确
	 */
	@RequestMapping("/resetPwd/{code}/{pwd}")
	@ResponseBody
	public boolean resetPwd(HttpServletRequest request,@PathVariable("code") String code,@PathVariable("pwd") String pwd) {
		String email = request.getParameter("email");
		if (userService.checkEmailCode(code,email)) {
			userService.resetPwd(pwd,email);
		}else {
			return false;
		}
		return true;
	}


	@Autowired
	private DefaultKaptcha defaultKaptcha;

	/**
	 * 验证码刷新
	 * @param request
	 * @param response
	 */
	@GetMapping(value = "/captcha", produces = "image/jpeg")
	public void captcha(HttpServletRequest request, HttpServletResponse response) {
		// 定义response输出类型为image/jpeg类型
		response.setDateHeader("Expires", 0);
		// Set standard HTTP/1.1 no-cache headers.
		response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
		// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");
		// Set standard HTTP/1.0 no-cache header.
		response.setHeader("Pragma", "no-cache");
		// return a jpeg
		response.setContentType("image/jpeg");
		//-------------------生成验证码 begin --------------------------
		//获取验证码文本内容
		String text = defaultKaptcha.createText();
		//将验证码文本内容放入session
		request.getSession().setAttribute("captcha", text);
		//根据文本验证码内容创建图形验证码
		BufferedImage image = defaultKaptcha.createImage(text);
		ServletOutputStream outputStream = null;
		try {
			outputStream = response.getOutputStream();
			//输出流输出图片，格式为jpg
			ImageIO.write(image, "jpg", outputStream);
			outputStream.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (null != outputStream) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
